package com.quatrix.openphantasy.server;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class Proxy extends HttpServlet {

	static Map<Pattern, String> route = new HashMap<Pattern, String>();
	static {
		route.put(Pattern.compile("^.+/CountryService"),
				"http://localhost:8000/server/CountryService");
		route.put(Pattern.compile("^.+/TeamService"),
		"http://localhost:8000/server/TeamService");
		route.put(Pattern.compile("^.+/LeagueService"),
		"http://localhost:8000/server/LeagueService");

	}
	

	static String getRoutedUrlBase(HttpServletRequest req) {
		String uri = req.getRequestURI();

		Set<Pattern> patterns = route.keySet();
		for (Pattern pattern : patterns) {
			Matcher m = pattern.matcher(uri);
			if (m.matches()) {
				return route.get(pattern);
			}
		}

		return null;
	}

	protected void doPost(HttpServletRequest req, HttpServletResponse res)
			throws ServletException, IOException {

		String strUrlBase = getRoutedUrlBase(req);
		if (strUrlBase == null) {
			throw new ServletException();
		}

		String post = null;
		Set entrySet = req.getParameterMap().entrySet();
		Map headers = new HashMap();
		for (Iterator iter = entrySet.iterator(); iter.hasNext();) {
			Map.Entry header = (Map.Entry) iter.next();
			String key = (String) header.getKey();
			String value = ((String[]) header.getValue())[0];

			if (key.compareTo("post") == 0) {
				post = value;
			} else {
				headers.put(key, value);
			}
		}

		// Forward the query string as well
		// Technically, this code should be inside doGet()
		StringBuilder urlString = new StringBuilder(strUrlBase);
		String queryString = req.getQueryString();

		if (queryString != null && !queryString.equals("")) {
			urlString.append("?");
			urlString.append(queryString);
		}

		URL url = new URL(urlString.toString());

		if (url != null) {
			boolean complete = false;
			while (!complete) {

				HttpURLConnection urlConnection = (HttpURLConnection) url
						.openConnection();
				urlConnection.setDoOutput(true);
				urlConnection.setDoInput(true);
				urlConnection.setUseCaches(false);
				urlConnection.setInstanceFollowRedirects(false);
				urlConnection.setRequestMethod("GET");

				// urlConnection.setConnectTimeout(5000);

				// set headers

				Set headersSet = headers.entrySet();
				for (Iterator iter = headersSet.iterator(); iter.hasNext();) {
					Map.Entry header = (Map.Entry) iter.next();
					urlConnection.setRequestProperty((String) header.getKey(),
							(String) header.getValue());
				}

				// send post
				if (post != null) {
					OutputStreamWriter outRemote = new OutputStreamWriter(
							urlConnection.getOutputStream());
					outRemote.write(post);
					outRemote.flush();
				}

				// get content type
				String contentType = urlConnection.getContentType();
				if (contentType != null)
					res.setContentType(contentType);

				// get reponse code
				int responseCode = urlConnection.getResponseCode();

				if (responseCode == 302) {
					String location = urlConnection.getHeaderField("Location");
					url = new URL(location);
				} else {
					res.setStatus(responseCode);
					BufferedInputStream in;
					if (responseCode == 200 || responseCode == 201)
						in = new BufferedInputStream(urlConnection
								.getInputStream());
					else
						in = new BufferedInputStream(urlConnection
								.getErrorStream());

					// send output to client
					BufferedOutputStream out = new BufferedOutputStream(res
							.getOutputStream());
					int c;
					while ((c = in.read()) >= 0)
						out.write(c);
					out.flush();
					complete = true;
				}
			}
		}
	}

	protected void doGet(HttpServletRequest req, HttpServletResponse res)
			throws ServletException, IOException {
		doPost(req, res);
	}
}
